/**
 * 更好的引入方式
 */
import * as React from "react"
import * as ReactDOM from "react-dom"

/**
 * 函数式组件的声明方式
 */
//第一种 FC
type Iprops = {
    id: number
    name: string
}

const App: React.FC<Iprops> = ({ id, name, children }) => {
    return (
        <div>{name}</div>
    )
}

const App2: React.FC<{}> = props => props.children as any

const App3: React.FC<{}> = () => [1, 2, 3] as any

//第二种 PropsWithChildren
type AppProps = React.PropsWithChildren<{ name: string }>

const App4 = ({ name, children }: AppProps) => {
    return <div>{name}</div>
}

//第三种 直接声明
type AppPropsOnther = {
    name: string
    children?: React.ReactNode
}

const App5 = ({ name, children }: AppPropsOnther) => {
    return (
        <div>{name}</div>
    )
}

/**
 * hooks
 */

//useState
//自动推断类型
const [state1] = React.useState({ name: 'kaho' })

const showName = React.useCallback((obj: typeof state1) => {
    return `${obj.name}`
}, [])

//初始值为null时需要显示声明类型
type User = {
    name: string
}

const [user] = React.useState<User | null>(null)

//useRef
const ref1 = React.useRef<HTMLInputElement>(null!)
const ref2 = React.useRef<HTMLInputElement | null>(null)

const ref = React.useRef<number>(0)

React.useEffect(() => {
    ref.current += 1
    ref1.current.focus()
    ref2.current?.focus()
}, [])

//useEffect
const value: number = 1

//useMemo, useCallback
const valueMemo = React.useMemo(() => value * 2, [value])

// 自动推断 (value: number) => number
const multiplier = 2

const multiply = React.useCallback((value: number) => value * multiplier, [
    multiplier
])

//泛型
//指定返回值的类型
const result = React.useMemo<number>(() => 2, [])

//指定参数类型
const handlerChange = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>((e) => { console.log(e.target.value) }, [])

//自定义hooks
// function useLoading(): [
//     boolean,
//     (aPromise: Promise<any>) => Promise<any>
// ] {
//     const [isLoading, setState] = React.useState(false)

//     const load = (aPromise: Promise<any>) => {
//         setState(true)
//         return aPromise.then(() => setState(false))
//     }

//     return [isLoading, load]
// }



function tuplify<T extends any[]>(...elements: T) {

    return elements

}



function useLoading() {

    const [isLoading, setState] = React.useState(false)

    const load = (aPromise: Promise<any>) => {

        setState(true)

        return aPromise.then(() => setState(false))

    }



    // (boolean | typeof load)[]

    return [isLoading, load]

}



function useTupleLoading() {

    const [isLoading, setState] = React.useState(false)

    const load = (aPromise: Promise<any>) => {

        setState(true)

        return aPromise.then(() => setState(false))

    }



    // [boolean, typeof load]

    return tuplify(isLoading, load)

}

/**
 * interface
 * type
 */


class Point {

    x: number = 2

    y: number = 3

}



interface IShape {

    area(): number

}



type Perimeter = {

    perimeter(): number

}



type RectangleShape = (IShape | Perimeter) & Point



// class Rectangle implements RectangleShape {

//     // 类只能实现具有静态已知成员的对象类型或对象类型的交集。

//     x = 2

//     y = 3

//     area() {

//         return this.x + this.y

//     }

// }



// interface ShapeOrPerimeter extends RectangleShape { }

// 接口只能扩展使用静态已知成员的对象类型或对象类型的交集

//泛型示例
type BProps<T> = {
    name: T
}

const TestB: <T>(props: BProps<T>) => React.ReactElement = ({ name }) => {

    return (

        <div className="test-b">

            TestB--{name}

        </div>

    )

}

<TestB<number> name={123} />

type Demo = {
    one: string
    two: string
    three: string
}

type MyPartial<T> = {[P in keyof T]?: T[P]}

type Demoo = MyPartial<Demo>